TerraformのMultiple Providersを利用して東京/オレゴンリージョン間でVyOSを利用したVPNコネクションを構築する
はじめに
こんにちは、中山です。
VPCにはハードウェアVPN機能があります。VGWとCGW間でVPNコネクションを構築できる機能です。詳細は下記エントリを参照してください。
検証目的でハードウェアVPN環境を構築しようと考えたのですが、必要な構成要素が多く環境の構築に時間が掛るという印象があります。今回TerraformのMultiple Providersという機能を利用してさくっと検証環境を構築できるようにコード化してみました。CGWにはVyOSを利用しています。
Multiple Providersとは
Terraformはproviderという単位でresourceを管理します。例えば、AWSのresourceを使いたい場合awsというproviderを利用します。providerは基本的に1つのprovider毎にリージョンを設定します。そのため、例えば東京/オレゴンリージョン両方にVPCを作りたい場合、1つのproviderでは片方のリージョンにしかVPCを作ることができません。もちろん、 tf
ファイルをprovider毎に用意するという方法で構築することも可能ですが、コードが分散してしまい管理しづらくなります。
そこでMultiple Providersです。providerの引数に alias
という設定を記述することで、1つのコード上に複数のproviderを設定できる機能です。記述例をドキュメントから引用します。
- providerの設定
# The default provider provider "aws" { # ... } # West coast region provider "aws" { alias = "west" region = "us-west-2" }
alias
を設定したproviderを参照する場合はresourceに <provider-name>.<alias-name>
という書式で記述することにより参照可能です。 alias
を設定していないデフォルトのproviderは何も設定しない場合に参照されます。記述例をドキュメントから引用します。
- providerの参照
resource "aws_instance" "foo" { provider = "aws.west" # ... }
Multiple Providersのご紹介をしました。では、早速使ってみましょう。
構成図
今回構築する構成は以下のとおりです。
東京/オレゴンリージョンにそれぞれVPCを1つずつ構築します。オレゴンリージョンにEC2を1つ、東京リージョンにCGWとしてVyOSを1つ構築します。オレゴンリージョンにVGWを設定して、VyOSとVPNコネクションを結びます。
コード
GitHubに上げておきました。ご自由にお使いください。
コードの解説
主要なコードを抜粋して解説します。
main.tf
このファイルでMultiple Providersの設定をしています。以下の例では aws.oregon
でオレゴンリージョンのproviderを参照可能です。
provider "aws" { region = "${var.regions["tokyo"]}" } provider "aws" { alias = "oregon" region = "${var.regions["oregon"]}" }
ちなみに、v.0.7.0から配列やマップをそれぞれ、 list[index]
と map["key"]
の形式で参照できるようになりました。便利。
network_oregon.tf
resource "aws_vpn_gateway" "vgw" { provider = "aws.oregon" vpc_id = "${aws_vpc.vpc_oregon.id}" } resource "aws_customer_gateway" "cgw" { provider = "aws.oregon" bgp_asn = 65000 ip_address = "${aws_instance.vyos_tokyo.public_ip}" type = "ipsec.1" } resource "aws_vpn_connection" "vpn" { provider = "aws.oregon" vpn_gateway_id = "${aws_vpn_gateway.vgw.id}" customer_gateway_id = "${aws_customer_gateway.cgw.id}" type = "ipsec.1" static_routes_only = false tags { Name = "${var.name}" } }
それぞれVGW/CGW/VPNコネクションの作成をしています。resourceに指定する引数はドキュメントを参照してください。
注意点としてVyOSのコンフィグはVPNコネクションのルーティングをDynamicにしないとダウンロードできないため、 static_routes_only
を false
にしておく必要があります。
続いて、ルートテーブルの設定です。
resource "aws_route_table" "public_oregon" { provider = "aws.oregon" vpc_id = "${aws_vpc.vpc_oregon.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.public_oregon.id}" } route { cidr_block = "${var.vpc_cidrs["tokyo"]}" gateway_id = "${aws_vpn_gateway.vgw.id}" } }
aws_route_table resourceでルートテーブルを作成しています。東京リージョンのVPC宛の通信はVGWへ向ける必要があるので、ハイライトしている記述が必要です。
network_tokyo.tf
オレゴンリージョンへの通信はCGWであるVyOSを経由して行われるので以下のようにハイライトしている記述が必要です。
resource "aws_route_table" "public_tokyo" { vpc_id = "${aws_vpc.vpc_tokyo.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.public_tokyo.id}" } route { cidr_block = "${var.vpc_cidrs["oregon"]}" instance_id = "${aws_instance.vyos_tokyo.id}" } }
variables.tf
v.0.7.0から導入される予定のData SourcesにもMultiple Providersは利用できます。
data "aws_availability_zones" "az_tokyo" {} data "aws_availability_zones" "az_oregon" { provider = "aws.oregon" }
例えば、上記設定では data.aws_availability_zones.az_tokyo.names[0]
でap-northeast-1aを、 data.aws_availability_zones.az_oregon.names[0]
でus-west-2aを参照可能です。
コードの実行方法
2016/07/04時点でまだリリースされていないTerraform v.0.7.0の機能を利用しているのでv0.7.0-rc2を利用します。インストール方法は下記エントリを参照してください。
Terraformの実行
コードのcloneとkeypair作成後いつもどおりTerraformを実行すればOKです。Terraformバイナリへのパスは適宜修正してください。
$ git clone https://github.com/knakayama/tf-vpc-vpn-demo.git $ cd tf-vpc-vpn-demo $ ssh-keygen -f site_key -N '' $ $GOPATH/bin/terraform plan $ $GOPATH/bin/terraform apply <snip> Outputs: ec2_oregon = public ip: 54.201.254.17 private ip: 10.0.1.118 vyos_tokyo = public ip: 54.238.189.58 private ip: 10.0.1.118
VyOSの設定
Terraformの実行が完了したらAMCからコンフィグをダウンロードします。VendorはVyattaを選択してください。
コンフィグをダウンロード後、東京リージョンで起動しているVyOSに設定を投入します。 /bin/vbash
はエクスクラメーションマークがコメントとして扱われないようなのでgsedで加工して実行しています。また、 local-address
をVyOSのprivate ipに変換します。
$ gsed -E \ -e 's/^!/#/g' \ -e '1i\source /opt/vyatta/etc/functions/script-template\nconfigure' \ -e '$a\commit' \ -e "s/local-address '54\.238\.189\.58'/local-address '10\.0\.1\.118'/g" \ path/to/config \ | ssh -i keys/site_key [email protected] /bin/vbash
設定投入後、VPNコネクションのステータスがUPになっていることを確認してください。
$ aws ec2 describe-vpn-connections \ --region us-west-2 \ --query 'VpnConnections[?Tags[?Value==`tf-vpc-vpn-demo`]].VgwTelemetry' [ [ { "Status": "UP", "AcceptedRouteCount": 1, "OutsideIpAddress": "52.40.119.170", "LastStatusChange": "2016-07-02T17:44:05.000Z", "StatusMessage": "1 BGP ROUTES" }, { "Status": "UP", "AcceptedRouteCount": 1, "OutsideIpAddress": "52.40.227.207", "LastStatusChange": "2016-07-02T17:43:49.000Z", "StatusMessage": "1 BGP ROUTES" } ] ]
疎通確認
東京/オレゴンリージョンに作成したインスタンスにログインしてprivate ipに対し、お互いにpingを打ってみましょう。
- オレゴンリージョン
$ ssh -i keys/site_key [email protected] $ ping -c 1 10.0.1.118 PING 10.0.1.118 (10.0.1.118) 56(84) bytes of data. 64 bytes from 10.0.1.118: icmp_seq=1 ttl=64 time=100 ms --- 10.0.1.118 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 100.122/100.122/100.122/0.000 ms
- 東京リージョン
$ ssh -i keys/site_key [email protected] $ ping 172.16.1.160 interface 10.0.1.118 count 1 PING 172.16.1.160 (172.16.1.160) from 10.0.1.118 : 56(84) bytes of data. 64 bytes from 172.16.1.160: icmp_req=1 ttl=254 time=101 ms --- 172.16.1.160 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 101.110/101.110/101.110/0.000 ms
疎通が取れているようです。やりましたね。
まとめ
いかがだったでしょうか。
VPCのハードウェアVPNは導入案件が多い割に少し敷居の高いサービスでもあります。しかし、TerraformやVyOSを利用することにより手軽に検証環境が構築できることを確認しました。
本エントリがみなさんの参考になれば幸いです。